#ifndef VENUS_DEPTHPEELING_DEPTHPEELINGDEMO_H
#define VENUS_DEPTHPEELING_DEPTHPEELINGDEMO_H

#include "common/venus.h"
#include "ui/glut_window.h"
#include "graphics/camera.h"
#include "graphics/fps_counter.h"

namespace venus {
class DepthPeelingDemo : public GlutWindow {
 public:
  DepthPeelingDemo();
  ~DepthPeelingDemo();
  bool Initialize(const char *model_file);
  void OnIdle();
  void OnDisplay();
  void OnResize(int width, int height);
  void OnKeyboard(unsigned char key, int x, int y);
 private:
  bool LoadShaders();
  void ReleaseShaders();
  void DeleteFrontPeelingRenderTargets();
  bool InitFrontPeelingRenderTargets();
  void DeleteDualPeelingRenderTargets();
  bool InitDualPeelingRenderTargets();
  void DeleteAccumulationRenderTargets();
  bool InitAccumulationRenderTargets();
  void DeleteBucketPeelingRenderTargets();
  bool InitBucketPeelingRenderTargets();
  
  void RenderFrontToBackPeeling();
  void RenderDualDepthPeeling();
  void RenderBucketDepthPeeling();
  void RenderGL();
  void RenderModel();
  void RenderModelBound();
 private:
  TriangleMesh *model_;
  ModelGL *model_gl_;
  RenderDeviceFBO *device_;
  RenderDeviceFBO *dual_peeling_device_;
  RenderDeviceFBO *bucket_peeling_device_;

  ImageTextureGL *front_depth_targets_[2];
  ImageTextureGL *front_color_targets_[2];
  ImageTextureGL *front_color_blender_target_;
  ProgramGLSL *front_init_program_;
  ProgramGLSL *front_peeling_program_;
  ProgramGLSL *front_blend_program_;
  ProgramGLSL *front_final_program_;

  ImageTextureGL *dual_back_temp_targets_[2];
  ImageTextureGL *dual_depth_targets_[2];
  ImageTextureGL *dual_front_blender_targets_[2];
  ImageTextureGL *dual_back_blender_target_;
  ProgramGLSL *dual_init_program_;
  ProgramGLSL *dual_peel_program_;
  ProgramGLSL *dual_blend_program_;
  ProgramGLSL *dual_final_program_;
  GLenum mrt_[8];

  ImageTextureGL *bucket_min_max_depth_target_;
  ImageTextureGL *bucket_depth_targets_[8];
  ProgramGLSL *bucket_init_program_;
  ProgramGLSL *bucket_peel_program_;
  ProgramGLSL *bucket_final_program_;

  OrbitPerspectiveCameraGL camera_;

  float translate_y_;

  GLuint quad_display_list_;
  float alpha_;
  int peeling_method_;
  bool demo_ready_;

  FpsCounter fps_counter_;
};
} // namespace venus

#endif // VENUS_DEPTHPEELING_DEPTHPEELINGDEMO_H
